home *** CD-ROM | disk | FTP | other *** search
- /*
- * CLIENT routines for Simple Mail Transfer Protocol ala RFC821
- * A.D. Barksdale Garbee II, aka Bdale, N3EUA
- * Copyright 1986 Bdale Garbee, All Rights Reserved.
- * Permission granted for non-commercial copying and use, provided
- * this notice is retained.
- * Modified 14 June 1987 by P. Karn for symbolic target addresses,
- * also rebuilt locking mechanism
- * Copyright 1987 1988 David Trulli, All Rights Reserved.
- * Permission granted for non-commercial copying and use, provided
- * this notice is retained.
- */
- #include <stdio.h>
- #include <fcntl.h>
- #include <time.h>
- #include <setjmp.h>
- #include <ctype.h>
- #ifdef UNIX
- #include <sys/types.h>
- #endif
- #ifdef AMIGA
- #include "stat.h"
- #else
- #include <sys/stat.h>
- #endif
- #ifdef __TURBOC__
- #include <dir.h>
- #include <io.h>
- #endif
- #include "global.h"
- #include "config.h"
- #ifdef ANSIPROTO
- #include <stdarg.h>
- #endif
- #include "cmdparse.h"
- #include "proc.h"
- #include "socket.h"
- #ifdef LZW
- #include "lzw.h"
- #endif
- #include "timer.h"
- #include "netuser.h"
- #include "smtp.h"
- #include "dirutil.h"
- #include "commands.h"
- #include "session.h"
- #include "files.h"
-
- int16 Smtpquiet = 0;
- int Smtpmode = 0;
- static int Smtpsessions = 0; /* number of client connections */
- static struct timer Smtpcli_t;
- static int32 Gateway;
- static unsigned short Smtpmaxcli = MAXSESSIONS; /* the max client connections allowed */
- static struct smtpcli *cli_session[MAXSESSIONS]; /* queue of client sessions */
-
- #ifdef SMTPTRACE
- static int Smtptrace = 0; /* used for trace level */
- static int dosmtptrace __ARGS((int argc,char *argv[],void *p));
- #endif
-
- #ifdef LZW
- int Smtplzw = 1;
- static int Smtpbatch = 1;
- #else
- static int Smtpbatch = 0;
- #endif
-
- static int near getresp __ARGS((struct smtpcli *ftp,int mincode));
- static void near logerr __ARGS((struct smtpcli *cb,char *line));
- static void smtp_send __ARGS((int unused,void *cb1,void *p));
- static void near del_job __ARGS((struct smtp_job *jp));
- static struct smtpcli * near lookup __ARGS((int32 destaddr));
- static struct smtpcli * near newcb __ARGS((void));
- static struct smtp_job * near setupjob __ARGS((struct smtpcli *cb,char *id,char *from));
- static void near del_session __ARGS((struct smtpcli *cb));
- static void near retmail __ARGS((struct smtpcli *cb));
- static int near next_job __ARGS((struct smtpcli *cb));
-
- /* delete a list of list structs */
- void
- del_list(lp)
- struct list *lp;
- {
- struct list *tp, *tp1 = NULLLIST;
-
- for (tp = lp; tp != NULLLIST; tp = tp1) {
- tp1 = tp->next;
- xfree(tp->val);
- xfree((char *)tp);
- }
- }
-
- static void near
- del_job(jp)
- struct smtp_job *jp;
- {
- if ( *jp->jobname != '\0')
- rmlock(Mailqdir,jp->jobname);
- xfree(jp->from);
- del_list(jp->to);
- xfree((char *)jp);
- }
-
- /* free the message struct and data */
- static void near
- del_session(cb)
- struct smtpcli *cb;
- {
- struct smtp_job *jp,*tp;
- int i;
-
- if (cb == NULLSMTPCLI)
- return;
- for(i=0; i<MAXSESSIONS; i++)
- if(cli_session[i] == cb) {
- cli_session[i] = NULLSMTPCLI;
- break;
- }
-
- xfree(cb->wname);
- xfree(cb->tname);
- xfree(cb->destname);
- for (jp = cb->jobq; jp != NULLJOB; jp = tp) {
- tp = jp->next;
- del_job(jp);
- }
- del_list(cb->errlog);
- xfree((char *)cb);
- Smtpsessions--; /* number of connections active */
- }
-
- /* called to advance to the next job */
- static int near
- next_job(cb)
- struct smtpcli *cb;
- {
- struct smtp_job *jp = cb->jobq->next;
-
- del_job(cb->jobq);
- /* remove the error log of previous message */
- del_list(cb->errlog);
- cb->errlog = NULLLIST;
- cb->jobq = jp;
- if (jp == NULLJOB)
- return 0;
- sprintf(cb->tname,"%s/%s.txt",Mailqdir,jp->jobname);
- sprintf(cb->wname,"%s/%s.wrk",Mailqdir,jp->jobname);
- #ifdef SMTPTRACE
- if (Smtptrace) {
- tprintf("sending job %s\n",jp->jobname);
- }
- #endif
- return 1;
- }
-
- /* create a new smtp control block */
- static struct smtpcli * near
- newcb()
- {
- int i;
- struct smtpcli *cb;
-
- for(i=0; i<MAXSESSIONS; i++) {
- if(cli_session[i] == NULLSMTPCLI) {
- cb = (struct smtpcli *)mxallocw(sizeof(struct smtpcli));
- cb->wname = mxallocw((unsigned)strlen(Mailqdir)+JOBNAME);
- cb->tname = mxallocw((unsigned)strlen(Mailqdir)+JOBNAME);
- cli_session[i] = cb;
- Smtpsessions++; /* number of connections active */
- return(cb);
- }
- }
- return NULLSMTPCLI;
- }
-
- /* look to see if a smtp control block exists for this ipdest */
- static struct smtpcli * near
- lookup(destaddr)
- int32 destaddr;
- {
- int i;
-
- for(i = 0; i < MAXSESSIONS; i++) {
- if (cli_session[i] == NULLSMTPCLI)
- continue;
- if(cli_session[i]->ipdest == destaddr)
- return cli_session[i];
- }
- return NULLSMTPCLI;
- }
-
- /* add this job to control block queue */
- static struct smtp_job * near
- setupjob(cb,id,from)
- struct smtpcli *cb;
- char *id,*from;
- {
- struct smtp_job *p2, *p1 =
- (struct smtp_job *)mxallocw(sizeof(struct smtp_job));
-
- p1->from = strxdup(from);
- strcpy(p1->jobname,id);
- /* now add to end of jobq */
- if ((p2 = cb->jobq) == NULLJOB)
- cb->jobq = p1;
- else {
- while(p2->next != NULLJOB)
- p2 = p2->next;
- p2->next = p1;
- }
- return p1;
- }
-
- /* This is the routine that gets called every so often to do outgoing
- * mail processing. When called with a null argument, it runs the entire
- * queue; if called with a specific non-zero IP address from the remote
- * kick server, it only starts up sessions to that address.
- */
- int
- smtptick(t)
- void *t;
- {
- struct smtpcli *cb;
- struct smtp_job *jp;
- struct list *ap;
- char tmpstring[LINELEN], wfilename[13], prefix[9];
- char from[LINELEN], to[LINELEN], *cp, *cp1;
- int32 destaddr,target;
- FILE *wfile;
- int i;
-
- stop_timer(&Smtpcli_t);
- target = (int32)t;
- #ifdef SMTPTRACE
- if (Smtptrace)
- tprintf("smtp daemon entered, target = %s\n",inet_ntoa(target));
- #endif
- if(availmem() < Memthresh){
- /* Memory is tight, don't do anything */
- /* Restart timer */
- start_timer(&Smtpcli_t);
- return 0;
- }
- for(filedir(Mailqueue,0,wfilename);wfilename[0] != '\0';
- filedir(Mailqueue,1,wfilename)){
- pwait(NULL);
- /* save the prefix of the file name which it job id */
- cp = wfilename;
- cp1 = prefix;
- while (*cp && *cp != '.')
- *cp1++ = *cp++;
- *cp1 = '\0';
-
- /* lock this file from the smtp daemon */
- if (mlock(Mailqdir,prefix))
- continue;
-
- sprintf(tmpstring,"%s/%s",Mailqdir,wfilename);
- if ((wfile = fopen(tmpstring,READ_TEXT)) == NULLFILE) {
- /* probably too many open files */
- rmlock(Mailqdir,prefix);
- /* continue to next message. The failure
- * may be temporary */
- continue;
- }
-
- fgets(tmpstring,sizeof(tmpstring),wfile); /* read target host */
- rip(tmpstring);
-
- if ((destaddr = mailroute(tmpstring)) == 0) {
- fclose(wfile);
- tprintf("*** smtp: Unknown address %s\n",tmpstring);
- rmlock(Mailqdir,prefix);
- continue;
- }
- if(target != 0 && destaddr != target){
- fclose(wfile);
- rmlock(Mailqdir,prefix);
- continue; /* Not the proper target of a kick */
- }
- #ifdef EVENT
- if (!testdelv(destaddr)) {
- fclose(wfile)
- rmlock(Mailqdir,prefix);
- continue;
- }
- #endif
- if ((cb = lookup(destaddr)) == NULLSMTPCLI) {
- /* there are enough processes running already */
- if (Smtpsessions >= Smtpmaxcli) {
- #ifdef SMTPTRACE
- if (Smtptrace) {
- tputs("smtp daemon: too many processes\n");
- }
- #endif
- fclose(wfile);
- rmlock(Mailqdir,prefix);
- break;
- }
- if ((cb = newcb()) == NULLSMTPCLI) {
- fclose(wfile);
- rmlock(Mailqdir,prefix);
- break;
- }
- cb->ipdest = destaddr;
- cb->destname = strxdup(tmpstring);
- } else {
- if(cb->lock){
- /* This system is already is sending mail lets not
- * interfere with its send queue.
- */
- fclose(wfile);
- rmlock(Mailqdir,prefix);
- continue;
- }
- }
-
- fgets(from,sizeof(from),wfile); /* read from */
- rip(from);
- if ((jp = setupjob(cb,prefix,from)) == NULLJOB) {
- fclose(wfile);
- rmlock(Mailqdir,prefix);
- del_session(cb);
- break;
- }
- while (fgets(to,sizeof(to),wfile) != NULLCHAR) {
- rip(to);
- if (addlist(&jp->to,to,DOMAIN) == NULLLIST) {
- fclose(wfile);
- del_session(cb);
- }
- }
- fclose(wfile);
- #ifdef SMTPTRACE
- if (Smtptrace) {
- tprintf("queue job %s From: %s To:",prefix,from);
- for (ap = jp->to; ap != NULLLIST; ap = ap->next)
- tprintf(" %s",ap->val);
- tputs("\n");
- }
- #endif
- }
-
- /* start sending that mail */
- for(i = 0; i < MAXSESSIONS; i++) {
- if((cb = cli_session[i]) == NULLSMTPCLI)
- continue;
- if(cb->lock)
- continue;
- sprintf(cb->tname,"%s/%s.txt",Mailqdir,cb->jobq->jobname);
- sprintf(cb->wname,"%s/%s.wrk",Mailqdir,cb->jobq->jobname);
- newproc("smtp_send", 2048, smtp_send, 0, cb, NULL, 0);
-
- #ifdef SMTPTRACE
- if (Smtptrace)
- tprintf("Trying Connection to %s\n",inet_ntoa(cb->ipdest));
- #endif
- }
- /* Restart timer */
- start_timer(&Smtpcli_t);
- return 0;
- }
-
- /* stub for calling mdaemon to return message to sender */
- static void near
- retmail(cb)
- struct smtpcli *cb;
- {
- FILE *infile;
- #ifdef SMTPTRACE
- if (Smtptrace) {
- tprintf("smtp job %s returned to sender\n",cb->wname);
- }
- #endif
- if ((infile = fopen(cb->tname,READ_TEXT)) == NULLFILE)
- return;
- mdaemon(infile,cb->jobq->from,cb->errlog,1);
- fclose(infile);
- }
-
- /* This is the master state machine that handles a single SMTP transaction.
- * It is called with a queue of jobs for a particular host.
- * The logic is complicated by the "Smtpbatch" variable, which controls
- * the batching of SMTP commands. If Smtpbatch is true, then many of the
- * SMTP commands are sent in one swell foop before waiting for any of
- * the responses. Unfortunately, this breaks many brain-damaged SMTP servers
- * out there, so provisions have to be made to operate SMTP in lock-step mode.
- */
- static void
- smtp_send(unused,cb1,p)
- int unused;
- void *cb1;
- void *p;
- {
- struct smtpcli *cb = (struct smtpcli *)cb1;
- struct list *tp;
- struct sockaddr_in fsocket;
- char *cp1;
- int smtpbatch, rcode, rcpts, goodrcpt, i, init = 1;
- #ifdef LZW
- int lzwmode, lzwbits;
- extern int16 Lzwbits;
- extern int Lzwmode;
- #endif
-
- cb->lock = 1;
- fsocket.sin_family = AF_INET;
- fsocket.sin_addr.s_addr = cb->ipdest;
- fsocket.sin_port = IPPORT_SMTP;
-
- cb->s = socket(AF_INET,SOCK_STREAM,0);
- sockmode(cb->s,SOCK_ASCII);
- setflush(cb->s,-1); /* We'll explicitly flush before reading */
-
- #ifdef SMTPTRACE
- if (Smtptrace)
- tputs("SMTP client Trying...\n");
- #endif
- if(connect(cb->s,(char *)&fsocket,SOCKSIZE) == 0){
- #ifdef SMTPTRACE
- if (Smtptrace)
- tputs("Connected\n");
- #endif
- ;
- } else {
- cp1 = sockerr(cb->s);
- #ifdef SMTPTRACE
- if (Smtptrace)
- tprintf("Connect failed: %s\n",cp1 != NULLCHAR ? cp1 : "");
- #endif
- log(cb->s,"SMTP %s Connect failed: %s",psocket(&fsocket),
- cp1 != NULLCHAR ? cp1 : "");
- }
- #ifdef LZW
- rcode = getresp(cb,200);
- if(rcode == -1 || rcode >= 400)
- goto quit;
-
- if(Smtplzw && cb->ipdest != Ip_addr) {
- char cp[LINELEN], *cp1, *cp2;
- usprintf(cb->s,"XLZW %d %d\n",Lzwbits,Lzwmode);
- usflush(cb->s);
-
- if(recvline(cb->s,cp,LINELEN) == -1)
- goto quit;
- rip(cp);
- if((cp1 = strchr(cp,' ')) == NULLCHAR)
- goto quit;
- *cp1 = '\0';
-
- smtpbatch = 1;
- if((rcode = atoi(cp)) == 252) {
- lzwinit(cb->s,Lzwbits,Lzwmode);
- } else if(rcode == 250) {
- lzwbits = LZWBITS;
- lzwmode = LZWMODE;
- cp1++;
- if((cp2 = strchr(cp1,' ')) != NULLCHAR) {
- *cp2 = '\0';
- lzwmode = atoi(cp1);
- cp1++;
- if((cp2 = strchr(cp1,' ')) != NULLCHAR) {
- *cp2 = '\0';
- lzwbits = atoi(cp1);
- } else {
- lzwmode = LZWMODE;
- }
- }
- lzwinit(cb->s,lzwbits,lzwmode);
- } else {
- smtpbatch = Smtpbatch;
- }
- } else {
- smtpbatch = Smtpbatch;
- }
- #else
- smtpbatch = Smtpbatch;
- if(!smtpbatch) {
- rcode = getresp(cb,200);
- if(rcode == -1 || rcode >= 400)
- goto quit;
- }
- #endif
-
- /* Say HELO */
- usprintf(cb->s,"HELO %s\n",Hostname);
- if(!smtpbatch){
- rcode = getresp(cb,200);
- if(rcode == -1 || rcode >= 400)
- goto quit;
- }
- do { /* For each message... */
-
- /* if this file open fails, skip it */
- if ((cb->tfile = fopen(cb->tname,READ_TEXT)) == NULLFILE)
- continue;
-
- /* Send MAIL and RCPT commands */
- usprintf(cb->s,"MAIL FROM:<%s>\n",cb->jobq->from);
- if(!smtpbatch){
- rcode = getresp(cb,200);
- if(rcode == -1 || rcode >= 400)
- goto quit;
- }
- rcpts = 0;
- goodrcpt = 0;
- for (tp = cb->jobq->to; tp != NULLLIST; tp = tp->next){
- usprintf(cb->s,"RCPT TO:<%s>\n",tp->val);
- if(!smtpbatch){
- rcode = getresp(cb,200);
- if(rcode == -1)
- goto quit;
- if(rcode < 400)
- goodrcpt = 1; /* At least one good */
- }
- rcpts++;
- }
- /* Send DATA command */
- usputs(cb->s,"DATA\n");
- if(!smtpbatch){
- rcode = getresp(cb,200);
- if(rcode == -1 || rcode >= 400)
- goto quit;
- }
- if(smtpbatch){
- /* Now wait for the responses to come back. The first time
- * we do this, we wait first for the start banner and
- * HELO response. In any case, we wait for the response to
- * the MAIL command here.
- */
- #ifdef LZW
- for(i = init ? 2 : 1; i > 0; i--) {
- #else
- for(i = init ? 3 : 1; i > 0; i--) {
- #endif
- rcode = getresp(cb,200);
- if(rcode == -1 || rcode >= 400)
- goto quit;
- }
- init = 0;
-
- /* Now process the responses to the RCPT commands */
- for(i=rcpts;i!=0;i--){
- rcode = getresp(cb,200);
- if(rcode == -1)
- goto quit;
- if(rcode < 400)
- goodrcpt = 1; /* At least one good */
- }
- /* And finally get the response to the DATA command.
- * Some servers will return failure here if no recipients
- * are valid, some won't.
- */
- rcode = getresp(cb,200);
- if(rcode == -1 || rcode >= 400)
- goto quit;
-
- /* check for no good rcpt on the list */
- if (goodrcpt == 0){
- usputs(cb->s,".\n"); /* Get out of data mode */
- goto quit;
- }
- }
- /* Send the file. This also closes it */
- strcpy(cb->buf,"\n");
- while(fgets(cb->buf,sizeof(cb->buf),cb->tfile) != NULLCHAR) {
- /* Escape a single '.' character at the beginning of a line */
- if(strcmp(cb->buf,".\n") == 0)
- usputc(cb->s,'.');
- usputs(cb->s,cb->buf);
- }
- fclose(cb->tfile);
- cb->tfile = NULLFILE;
- /* Send the end-of-message command */
- usprintf(cb->s,"%s.\n",(cb->buf[strlen(cb->buf)-1] == '\n') ? "" : "\n");
-
- /* Wait for the OK response */
- rcode = getresp(cb,200);
- if(rcode == -1)
- goto quit;
- if((rcode >= 200 && rcode < 300) || rcode >= 500){
- /* if a good transfer or permanent failure remove job */
-
- if (cb->errlog != NULLLIST)
- retmail(cb);
- /* Unlink the textfile */
- unlink(cb->tname);
- unlink(cb->wname); /* remove workfile */
- log(cb->s,"SMTP sent job %s To: %s From: %s",
- cb->jobq->jobname,cb->jobq->to->val,cb->jobq->from);
- }
- } while(next_job(cb));
- quit:
- usputs(cb->s,"QUIT\n");
- if (cb->errlog != NULLLIST){
- retmail(cb);
- unlink(cb->wname); /* unlink workfile */
- unlink(cb->tname); /* unlink text */
- }
- close_s(cb->s);
- if(cb->tfile != NULLFILE)
- fclose(cb->tfile);
- cb->lock = 0;
- del_session(cb);
- }
-
-
- /* create mail lockfile */
- int
- mlock(dir,id)
- char *dir,*id;
- {
- int fd;
- char lockname[LINELEN];
-
- #ifdef MSDOS
- if(strlen(id) > 8) { /* truncate long filenames */
- id[8] = '\0';
- if(id[7] == '/')
- id[7] = '\0';
- }
- #endif
- /* Try to create the lock file in an atomic operation */
- sprintf(lockname,"%s/%s.lck",dir,id);
- #ifdef AMIGA
- /* don't ask, really, just don't ask... I'd do file locking on
- * an Amiga much more differently than this.
- */
- if(access(lockname, 0) == 0)
- return -1;
- #endif
- fd = open(lockname, O_WRONLY|O_EXCL|O_CREAT,0600);
- if(fd != -1)
- close(fd);
- return (fd == -1) ? -1 : 0;
- }
-
- /* remove mail lockfile */
- int
- rmlock(dir,id)
- char *dir,*id;
- {
- char lockname[LINELEN];
-
- #ifdef MSDOS
- if(strlen(id) > 8) { /* truncate long filenames */
- id[8] = '\0';
- if(id[7] == '/')
- id[7] = '\0';
- }
- #endif
- sprintf(lockname,"%s/%s.lck",dir,id);
- return(unlink(lockname));
- }
-
- /* Mail routing function. For now just use the hosts file */
- int32
- mailroute(dest)
- char *dest;
- {
- int32 destaddr = 0;
-
- /* look up address or use the gateway */
- destaddr = resolve(dest);
- return ((destaddr != 0) ? destaddr : (Gateway != 0) ? Gateway : 0);
- }
-
- /* save line in error list */
- static void near
- logerr(cb,line)
- struct smtpcli *cb;
- char *line;
- {
- struct list *lp,*tp;
-
- tp = (struct list *)mxallocw(sizeof(struct list));
- tp->val = strxdup(line);
-
- /* find end of list */
- if ((lp = cb->errlog) == NULLLIST)
- cb->errlog = tp;
- else {
- while(lp->next != NULLLIST)
- lp = lp->next;
- lp->next = tp;
- }
- }
-
- /* Wait for, read and display response from server. Return the result code. */
- static int near
- getresp(cb,mincode)
- struct smtpcli *cb;
- int mincode; /* Keep reading until at least this code comes back */
- {
- int rval;
- char line[LINELEN];
-
- usflush(cb->s);
-
- for(;;){
- /* Get line */
- if(recvline(cb->s,line,sizeof(line)) == -1){
- rval = -1;
- break;
- }
- rip(line); /* Remove cr/lf */
- rval = atoi(line);
- #ifdef SMTPTRACE
- if(Smtptrace)
- tprintf("smtp recv: %s\n",line);/* Display to user */
- #endif
- if(rval >= 500) { /* Save permanent error replies */
- char tmp[LINELEN];
- if(cb->errlog == NULLLIST) {
- sprintf(tmp,"While talking to %s:",cb->destname);
- logerr(cb,tmp);
- }
- if(cb->buf[0] != '\0') { /* Save offending command */
- rip(cb->buf);
- sprintf(tmp,">>> %s",cb->buf);
- logerr(cb,tmp);
- cb->buf[0] = '\0';
- }
- sprintf(tmp,"<<< %s",line);
- logerr(cb,tmp); /* save the error reply */
- }
- /* Messages with dashes are continued */
- if(line[3] != '-' && rval >= mincode)
- break;
- }
- return rval;
- }
-
- /* ----------------------- SMTP Client subcmds ----------------------- */
-
- static int
- dobatch(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- return setbool(&Smtpbatch,"SMTP batching",argc,argv);
- }
-
- static int
- dogateway(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- int32 n;
-
- if(argc < 2){
- tprintf("SMTP gateway: %s\n",inet_ntoa(Gateway));
- } else if((n = resolve(argv[1])) == 0){
- tprintf(Badhost,argv[1]);
- return 1;
- } else
- Gateway = n;
- return 0;
- }
-
- static int
- smtpkick(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- int32 addr = 0;
- if(argc > 1 && (addr = resolve(argv[1])) == 0){
- tprintf(Badhost,argv[1]);
- return 1;
- }
- smtptick((void *)addr);
- return 0;
- }
-
- /* kill a job in the mqueue */
- static int
- dosmtpkill(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- char s[SLINELEN], *cp, c;
-
- sprintf(s,"%s/%s.lck",Mailqdir,argv[1]);
- cp = strrchr(s,'.');
- if (!access(s,0)) {
- Current->ttystate.echo = Current->ttystate.edit = 0;
- c = keywait("Warning, the job is locked by SMTP. Remove (y/n)? ",0);
- Current->ttystate.echo = Current->ttystate.edit = 1;
- if (c != 'y') {
- return 0;
- }
- unlink(s);
- }
- strcpy(cp,".wrk");
- if (unlink(s)) {
- tprintf("Job id %s not found\n",argv[1]);
- } else {
- strcpy(cp,".txt");
- unlink(s);
- }
- return 0;
- }
-
- /* list jobs wating to be sent in the mqueue */
- static int
- dosmtplist(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- char tstring[80], line[20], host[LINELEN], from[LINELEN], to[LINELEN];
- char status, *cp;
- struct stat stbuf;
- struct tm *tminfo, *localtime();
- FILE *fp;
-
- Current->flowmode = Cooked; /* Enable the more mechanism */
- tputs("S Job Size Date Time Host From\n");
-
- filedir(Mailqueue,0,line);
- while(line[0] != '\0') {
- sprintf(tstring,"%s/%s",Mailqdir,line);
- if ((fp = open_file(tstring,READ_TEXT,0,1)) == NULLFILE)
- continue;
- if ((cp = strrchr(line,'.')) != NULLCHAR)
- *cp = '\0';
- sprintf(tstring,"%s/%s.lck",Mailqdir,line);
- status = (access(tstring,0)) ? ' ' : 'L';
- sprintf(tstring,"%s/%s.txt",Mailqdir,line);
- stat(tstring,&stbuf);
- tminfo = localtime(&stbuf.st_ctime);
- fgets(host,sizeof(host),fp);
- rip(host);
- fgets(from,sizeof(from),fp);
- rip(from);
- tprintf("%c %7s %7ld %02d/%02d %02d:%02d %-16.16s %s\n",
- status,
- line,
- stbuf.st_size,
- tminfo->tm_mon+1,
- tminfo->tm_mday,
- tminfo->tm_hour,
- tminfo->tm_min,
- host,
- from);
- while (fgets(to,sizeof(to),fp) != NULLCHAR) {
- rip(to);
- tprintf(" To: %s\n",to);
- }
- fclose(fp);
- filedir(Mailqueue,1,line);
- }
- Current->flowmode = Raw;
- return 0;
- }
-
- static int
- dosmtpmaxcli(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- return setshort(&Smtpmaxcli,"SMTP maxcli",argc,argv);
- }
-
- static int
- setsmtpmode(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- if (argc < 2) {
- tprintf("SMTP mode: %s\n",(Smtpmode & QUEUE) ? "queue" : "route");
- } else {
- switch(tolower(*argv[1])) {
- case 'q':
- Smtpmode |= QUEUE;
- break;
- case 'r':
- Smtpmode &= ~QUEUE;
- break;
- default:
- tputs("Usage: smtp mode [queue|route]\n");
- break;
- }
- }
- return 0;
- }
-
- static int
- doquiet(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- return setintrc(&Smtpquiet,"SMTP quiet",argc,argv,0,3);
- }
-
- #ifdef LZW
- static int
- dosmtplzw(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- return setbool(&Smtplzw,"SMTP lzw",argc,argv);
- }
- #endif
-
- /* Set outbound spool scan interval */
- static int
- dotimer(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- if(argc < 2){
- tprintf("SMTP timer %lu/%lu s\n",
- read_timer(&Smtpcli_t)/1000L,
- dur_timer(&Smtpcli_t)/1000L);
- return 0;
- }
- stop_timer(&Smtpcli_t);
- /* what to call on timeout */
- Smtpcli_t.func = (void (*) __ARGS((void *)))smtptick;
- Smtpcli_t.arg = NULLCHAR; /* dummy value */
- set_timer(&Smtpcli_t,atol(argv[1]) * 1000L); /* set timer duration */
- start_timer(&Smtpcli_t); /* and fire it up */
- return 0;
- }
-
- #ifdef SMTPTRACE
- static int
- dosmtptrace(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- return setbool(&Smtptrace,"SMTP tracing",argc,argv);
- }
- #endif
-
- int
- dosmtp(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- struct cmds Smtpcmds[] = {
- "batch", dobatch, 0, 0, NULLCHAR,
- "delete", dosmtpkill, 0, 2, "smtp delete <jobnumber>",
- "gateway", dogateway, 0, 0, NULLCHAR,
- "kick", smtpkick, 0, 0, NULLCHAR,
- "list", dosmtplist, 0, 0, NULLCHAR,
- #ifdef LZW
- "lzw", dosmtplzw, 0, 0, NULLCHAR,
- #endif
- "maxclient", dosmtpmaxcli, 0, 0, NULLCHAR,
- "mode", setsmtpmode, 0, 0, NULLCHAR,
- "quiet", doquiet, 0, 0, NULLCHAR,
- "timer", dotimer, 0, 0, NULLCHAR,
- #ifdef SMTPTRACE
- "trace", dosmtptrace, 0, 0, NULLCHAR,
- #endif
- NULLCHAR,
- };
- return subcmd(Smtpcmds,argc,argv,p);
- }
-